package com.zmn.oms.zmn.business.impl.ins;

import com.alibaba.fastjson.JSON;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.ins.InsOrder;
import com.zmn.oms.model.entity.ins.InsOrderMaster;
import com.zmn.oms.model.entity.ins.InsOrderMasterQuery;
import com.zmn.oms.model.entity.ins.InsOrderMasterSync;
import com.zmn.oms.model.entity.master.OrderMaster;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkLogChange;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.master.OrderMasterService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.taobao.TaobaoTmcConstants;
import com.zmn.oms.zmn.business.interfaces.ins.InsOrderBService;
import com.zmn.oms.zmn.business.interfaces.ins.InsOrderNotifyService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 类描述：
 *
 * @author lhl
 * @date 2020/06/12 18:12
 */
@Slf4j
@Service
public class InsOrderNotifyServiceImpl implements InsOrderNotifyService {
    private static final String LOG_HEAD = "按单保险";

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    EngineerListRemoteService engineerListRemoteService;


    @Resource
    private OrderWorkService orderWorkService;
    @Resource
    private OrderMasterService orderMasterService;
    @Resource
    private OrderDetailService orderDetailService;
    @Autowired
    private InsOrderBService insOrderBService;
    @Resource
    private RedisManager redisManager;

    @Override
    public void notify(OrderWorkLogChange orderWorkLogChange) {
        if (orderWorkLogChange == null || orderWorkLogChange.getLogType() == null) {
            return;
        }

        if (orderWorkLogChange.getOpTime() == null) {
            orderWorkLogChange.setOpTime(new Date());
        }

        /*  2021.06.10 by lhl
        *   【家修匠订单】：
                1.派单：不处理；针对已存在保险师傅的情况：
                    # 再分单后派单（由其他公司变更到家修匠）：当前家修匠师傅尚未购买保险，保费由原师傅或公司负责；
                    # 转派单（变更主师傅）：由于都是家修匠师傅，所以不存在买保险师傅；
                2.多师傅：
                    -订单状态为已上门：给订单下的所有未投保的多师傅买保险，结束去掉的多师傅的保险；
                    -订单状态为未上门：不处理；针对已存在保险师傅的情况：同派单；
                3.上门：给订单下的所有师傅买保险；

            【非家修匠订单】：
                1.派单：给主师傅买保险；
                2.多师傅：给订单下的所有未投保的多师傅买保险，结束去掉的多师傅的保险；
                3.上门：不处理；
        */

        String orderIdStr = String.valueOf(orderWorkLogChange.getOrderId());

        switch (orderWorkLogChange.getLogType()) {
            case OrderLogConsts.ORDER_LOG_TYPE_TAKE:
                log.info("【{}】领单：orderId=[{}]", LOG_HEAD, orderIdStr);
                if (isDuplicateTakeOrVisit(OrderLogConsts.ORDER_LOG_TYPE_TAKE, orderIdStr)) {
                    log.info("【{}】重复的领单操作，已忽略：orderId=[{}]", LOG_HEAD, orderIdStr);
                    break;
                }
                // 派单处理
                this.onOrderDistributed(orderWorkLogChange);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_VISIT:
                log.info("【{}】上门：orderId=[{}]", LOG_HEAD, orderIdStr);
                if (isDuplicateTakeOrVisit(OrderLogConsts.ORDER_LOG_TYPE_VISIT, orderIdStr)) {
                    log.info("【{}】重复的上门操作，已忽略：orderId=[{}]", LOG_HEAD, orderIdStr);
                    break;
                }
                // 加修匠订单，上门时才买保险
                this.onOrderDistributed(orderWorkLogChange);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MULTI_MASTER:
                log.info("【{}】多师傅：orderId=[{}]", LOG_HEAD, orderIdStr);
                // 多工程师
                this.onMultiMasters(orderWorkLogChange);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CANCEL:
                log.info("【{}】订单取消：orderId=[{}]", LOG_HEAD, orderIdStr);
                // 取消订单
                this.onInsOrderEnd(orderWorkLogChange);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_COMPLETE:
                log.info("【{}】订单完成：orderId=[{}]", LOG_HEAD, orderIdStr);
                // 收单
                this.onInsOrderEnd(orderWorkLogChange);
                break;
            default:
                log.info("【{}】未知状态，不做处理：orderWorkLogChange=[{}]", LOG_HEAD,
                        JSON.toJSONString(orderWorkLogChange));
        }
    }

    /**
     * 消息去重
     * @param orderId
     * @return
     */
    private boolean isDuplicateMsg(String orderId) {
        String redisKey = String.format(RedisKeyConsts.INS_MQ_MSG_KEY, orderId);

        Long incr = redisManager.incr(redisKey);
        if (incr.intValue() > 1) {
            return true;
        }

        // 设置5分钟后自动过期，清除Redis占用
        redisManager.expire(redisKey, TaobaoTmcConstants.REDIS_EXPIRE_SECONDS);
        return false;
    }

    /**
     * 消息去重
     * @param orderId
     * @return
     */
    private boolean isDuplicateTakeOrVisit(int logType, String orderId) {
        String redisKey = String.format(RedisKeyConsts.INS_ORDER_DUPLICATE_TAKE_OR_VISIT_KEY,
                String.valueOf(logType), orderId
        );

        Long incr = redisManager.incr(redisKey);
        if (incr.intValue() > 1) {
            return true;
        }

        // 设置2秒钟后自动过期，清除Redis占用
        redisManager.expire(redisKey, 2);
        return false;
    }


    /**
     * 派单处理
     * @param orderWorkLogChange
     */
    private void onOrderDistributed(OrderWorkLogChange orderWorkLogChange) {
        Long orderId = orderWorkLogChange.getOrderId();

        // 派单有可能是自动操作，和确认几乎同时完成，产品数据有可能还没有同步到从库，所以需要从主库中取数据
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, orderWorkLogChange.getWorkId());

        boolean isJiaXiuJiang = Objects.equals(45111, dbOrderWork.getCompanyId());
        int logType = orderWorkLogChange.getLogType().intValue();
        if (isJiaXiuJiang && OrderLogConsts.ORDER_LOG_TYPE_VISIT != logType) {
            return; // 家修匠公司订单，由于失败率太高，上门时才给师傅买保险
        }
        if (!isJiaXiuJiang && OrderLogConsts.ORDER_LOG_TYPE_TAKE != logType) {
            return; // 非家修匠公司订单，领单时给师傅买保险
        }

        OrderDetail dbOrderDetail = orderDetailService.findOrderDetailByKeySrcMaster(orderId);

        // 查询是否已经同步
        InsOrder dbInsOrder = insOrderBService.findInsOrderByOrderId(orderId);

        // 首次派单
        if (dbInsOrder == null) {

            if (Objects.equals(GlobalConsts.PLAT_MARK_YEYX, dbOrderWork.getPlatWork())) {
                // 言而有信订单，不购买保险
                return;
            }

            List<OrderMaster> dbOrderMasters = orderMasterService
                    .listMasterByWorkId(dbOrderWork.getOrderId(), dbOrderWork.getWorkId());
            if (CollectionUtils.isEmpty(dbOrderMasters)) {
                log.warn("【{}】新增保险订单操作：未找到对应师傅信息。orderId=[{}]]", LOG_HEAD, orderId);
                return;
            }
            OrderMaster mainMaster = dbOrderMasters.stream()
                    .filter(item -> Objects.equals(dbOrderWork.getMasterId(), item.getMasterId()))
                    .findFirst().orElse(null);
            if (mainMaster == null) {
                // 没有找到主师傅，找从师傅作为补偿师傅
                mainMaster = dbOrderMasters.get(0);
            }

            // 参保订单
            InsOrder insOrder = _buildInsOrder(dbOrderWork, dbOrderDetail, mainMaster);
            insOrder.setCreateTime(orderWorkLogChange.getOpTime());

            // 接单师傅
            List<InsOrderMaster> addInsOrderMasters = new LinkedList<>();
            {
                // 主师傅
                addInsOrderMasters.add(
                        _buildInsOrderMaster(insOrder, null, true, true, null)
                );
                // 从师傅（学徒）
                for (OrderMaster item : dbOrderMasters) {
                    if (!Objects.equals(dbOrderWork.getMasterId(), item.getMasterId())) {
                        addInsOrderMasters.add(
                                _buildInsOrderMaster(insOrder, null, false, true, item)
                        );
                    }
                }
            }

            log.info("【{}】新增保险订单：insOrder=[{}], insOrderMasters=[{}]", LOG_HEAD, JSON.toJSONString(insOrder),
                    JSON.toJSONString(addInsOrderMasters));
            insOrderBService.saveInsOrder(insOrder, addInsOrderMasters);
        }
        // 改派订单
        else {
            InsOrder updateInsOrder = _buildUpdateInsOrder(dbInsOrder, dbOrderWork, dbOrderDetail);
            updateInsOrder.setUpdateTime(orderWorkLogChange.getOpTime());

            log.info("【{}】更新保险订单：insOrder=[{}], dbInsOrder=[{}]", LOG_HEAD, JSON.toJSONString(updateInsOrder),
                    JSON.toJSONString(dbInsOrder));
            _updateInsOrderAndMaster(updateInsOrder, dbInsOrder, dbOrderWork);
        }
    }

    /**
     * 多师傅
     * @param orderWorkLogChange
     */
    private void onMultiMasters(OrderWorkLogChange orderWorkLogChange) {
        Long orderId = orderWorkLogChange.getOrderId();

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderWorkLogChange.getWorkId());

        boolean isJiaXiuJiang = Objects.equals(45111, dbOrderWork.getCompanyId());
        int orderStatus = Optional.ofNullable(dbOrderWork.getStatus()).orElse(0);
        if (isJiaXiuJiang && OrderStatusConsts.WORK_STATUS_VISIT > orderStatus) {
            return; // 家修匠公司订单，由于失败率太高，上门后才给师傅买保险
        }
        if (!isJiaXiuJiang && OrderStatusConsts.WORK_STATUS_TAKE > orderStatus) {
            return; // 非家修匠公司订单，领单后给师傅买保险
        }

        OrderDetail dbOrderDetail = orderDetailService.findOrderDetailByKey(orderId);

        // 查询是否已经同步
        InsOrder dbInsOrder = insOrderBService.findInsOrderByOrderId(orderId);

        // 给所有接单师傅全部上保险，忽略师傅的保险配置。
        // 但是在之前的逻辑中，师傅没有配置买保险时，是不买保险的，这会导致订单没保存成保险订单，
        // 对于这种情况需要做兼容：将当前订单补录成保险订单
        if (dbInsOrder == null) {
            if (Objects.equals(GlobalConsts.PLAT_MARK_YEYX, dbOrderWork.getPlatWork())) {
                // 言而有信的订单，不购买保险
                return;
            }

            List<OrderMaster> dbOrderMasters = orderMasterService
                    .listMasterByWorkId(dbOrderWork.getOrderId(), dbOrderWork.getWorkId());
            if (CollectionUtils.isEmpty(dbOrderMasters)) {
                log.warn("【{}】新增保险订单操作：未找到对应师傅信息。orderId=[{}]]", LOG_HEAD, orderId);
                return;
            }
            OrderMaster mainMaster = dbOrderMasters.stream()
                    .filter(item -> Objects.equals(dbOrderWork.getMasterId(), item.getMasterId()))
                    .findFirst().orElse(null);
            if (mainMaster == null) {
                // 没有找到主师傅，找从师傅作为补偿师傅
                mainMaster = dbOrderMasters.get(0);
            }

            // 参保订单
            InsOrder insOrder = _buildInsOrder(dbOrderWork, dbOrderDetail, mainMaster);
            insOrder.setCreateTime(orderWorkLogChange.getOpTime());

            // 接单师傅
            List<InsOrderMaster> addInsOrderMasters = new LinkedList<>();
            {
                // 主师傅
                addInsOrderMasters.add(
                        _buildInsOrderMaster(insOrder, null, true, true, null)
                );
                // 从师傅（学徒）
                for (OrderMaster item : dbOrderMasters) {
                    if (!Objects.equals(dbOrderWork.getMasterId(), item.getMasterId())) {
                        addInsOrderMasters.add(
                                _buildInsOrderMaster(insOrder, null, false, true, item)
                        );
                    }
                }
            }

            log.info("【{}】新增保险订单：insOrder=[{}], insOrderMasters=[{}]", LOG_HEAD, JSON.toJSONString(insOrder),
                    JSON.toJSONString(addInsOrderMasters));
            insOrderBService.saveInsOrder(insOrder, addInsOrderMasters);
        }

        InsOrder updateInsOrder = _buildUpdateInsOrder(dbInsOrder, dbOrderWork, dbOrderDetail);
        updateInsOrder.setUpdateTime(orderWorkLogChange.getOpTime());

        log.info("【{}】更新保险订单：insOrder=[{}], dbInsOrder=[{}]", LOG_HEAD, JSON.toJSONString(updateInsOrder),
                JSON.toJSONString(dbInsOrder));
        _updateInsOrderAndMaster(updateInsOrder, dbInsOrder, dbOrderWork);
    }

    /**
     * 保险结束
     * @param orderWorkLogChange
     */
    private void onInsOrderEnd(OrderWorkLogChange orderWorkLogChange) {
        Long orderId = orderWorkLogChange.getOrderId();

        if (isDuplicateMsg(String.valueOf(orderId))) {
            log.info("【{}】订单结束重复消息，已忽略：orderId=[{}]", LOG_HEAD, orderId);
            return;
        }

        InsOrder dbInsOrder = insOrderBService.findInsOrderByOrderId(orderId);
        if (dbInsOrder == null) {
            return;
        }

        Date opTime = orderWorkLogChange.getOpTime();

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderWorkLogChange.getWorkId());
        OrderDetail dbOrderDetail = orderDetailService.findOrderDetailByKey(orderId);

        // 构建按单保险信息
        InsOrder updateInsOrder = _buildUpdateInsOrder(dbInsOrder, dbOrderWork, dbOrderDetail);
        // 设置保险结束时间
        updateInsOrder.setUpdateTime(opTime);
        updateInsOrder.setCompleteTime(opTime);

        // 构建承担保费的师傅信息
        InsOrderMasterSync insOrderMasterSync = _buildOrderMasterSync(dbInsOrder, dbOrderWork, dbOrderDetail, opTime);

        // 获取当前在保师傅
        List<InsOrderMaster> dbInsOrderMasters = null;
        {
            InsOrderMasterQuery insOrderMasterQuery = new InsOrderMasterQuery();
            insOrderMasterQuery.setInsId(updateInsOrder.getInsId());
            insOrderMasterQuery.setStatus(GlobalConsts.YES);
            dbInsOrderMasters = insOrderBService.listInsOrderMasters(insOrderMasterQuery);

            if (dbInsOrderMasters != null && dbInsOrderMasters.size() > 0) {
                for (InsOrderMaster item : dbInsOrderMasters) {
                    // 老版本中没有记录师傅所属平台，需要兼容老数据 2020-06-23 by lhl
                    if (item.getPlatWork() == null) {
                        ForeignEngineerDetailInfoDRO mastMasterDRO = _queryMasterInfo(item.getMasterId());
                        if (mastMasterDRO != null && mastMasterDRO.getPlat() != null) {
                            item.setPlatWork(mastMasterDRO.getPlat());
                        }
                        else {
                            Integer plat = Optional
                                    .ofNullable(updateInsOrder.getPlatWork())
                                    .orElse(GlobalConsts.PLAT_MARK_ZMN);
                            item.setPlatWork(plat);
                        }
                    }
                }
            }
        }

        log.info("【{}】结束保险订单：insOrder=[{}], dbInsOrder=[{}], insOrderMasterSync=[{}]", LOG_HEAD,
                JSON.toJSONString(updateInsOrder),
                JSON.toJSONString(dbInsOrder),
                JSON.toJSONString(insOrderMasterSync));
        // 结束保险的师傅
        insOrderBService.endInsOrderAndMasters(updateInsOrder, dbInsOrderMasters, insOrderMasterSync);
    }

    public static void main(String[] args) {
        System.out.println(JSON.toJSONString(null));
    }
    /**
     * 更新保险订单信息 & 更新参保师傅信息
     */
    private void _updateInsOrderAndMaster(InsOrder updateInsOrder, InsOrder dbInsOrder, OrderWork dbOrderWork) {
        boolean isYeyx = Objects.equals(GlobalConsts.PLAT_MARK_YEYX, dbOrderWork.getPlatWork());

        // 找出新增师傅 & 退出师傅（包括主师傅和从师傅）
        List<InsOrderMaster> addInsOrderMasters = new LinkedList<>();
        List<InsOrderMaster> delInsOrderMasters = new LinkedList<>();

        { // 分别找出新增师傅，需要结束保险的师傅
            // 当前在保师傅
            InsOrderMasterQuery insOrderMasterQuery = new InsOrderMasterQuery();
            insOrderMasterQuery.setInsId(updateInsOrder.getInsId());
            insOrderMasterQuery.setStatus(GlobalConsts.YES);
            List<InsOrderMaster> dbInsOrderMasters = insOrderBService.listInsOrderMasters(insOrderMasterQuery);
            // 当前订单师傅 OrderConsts.ORDER_MASTER_TYPE_SLAVE
            List<OrderMaster> dbOrderMasters = orderMasterService
                    .listMasterByWorkId(dbOrderWork.getOrderId(), dbOrderWork.getWorkId());

            // 找出需要结束保险的师傅
            Map<Integer, OrderMaster> orderMasterFilter =
                    dbOrderMasters.stream().collect(
                            Collectors.toMap(OrderMaster::getMasterId, Function.identity(), (item1, item2) -> item2)
                    );
            dbInsOrderMasters.forEach(item -> {
                if (!orderMasterFilter.containsKey(item.getMasterId())) {
                    // 老版本中没有记录师傅所属平台，需要兼容老数据 2020-06-23 by lhl
                    if (item.getPlatWork() == null) {
                        ForeignEngineerDetailInfoDRO mastMasterDRO = _queryMasterInfo(item.getMasterId());
                        if (mastMasterDRO != null && mastMasterDRO.getPlat() != null) {
                            item.setPlatWork(mastMasterDRO.getPlat());
                        }
                        else {
                            item.setPlatWork(Optional.ofNullable(dbInsOrder).orElse(updateInsOrder).getPlatWork());
                        }
                    }
                    delInsOrderMasters.add(item);
                }
            });

            // 找出新增师傅(言而有信订单师傅不买保险)
            if (!isYeyx) {
                Map<Integer, InsOrderMaster> insMasterFilter =
                        dbInsOrderMasters.stream().collect(
                                Collectors.toMap(InsOrderMaster::getMasterId, Function.identity(), (item1, item2) -> item2)
                        );
                dbOrderMasters.forEach(item -> {
                    if (!insMasterFilter.containsKey(item.getMasterId())) {
                        boolean isMainMaster = Objects.equals(OrderConsts.ORDER_MASTER_TYPE_MAIN, item.getType());
                        InsOrderMaster addInsMaster =
                                _buildInsOrderMaster(updateInsOrder, dbInsOrder, isMainMaster, true, item);
                        addInsMaster.setCreateTime(updateInsOrder.getUpdateTime());
                        addInsOrderMasters.add(addInsMaster);
                    }
                });
            }
        }

        insOrderBService.updateInsOrderAndMasters(updateInsOrder, addInsOrderMasters, delInsOrderMasters);
    }

    /**
     * 构建承担保费师傅信息实例
     * @param dbInsOrder
     * @param orderWork
     * @param orderDetail
     * @param opTime
     * @return
     */
    private InsOrderMasterSync _buildOrderMasterSync(InsOrder dbInsOrder,
                                                     OrderWork orderWork,
                                                     OrderDetail orderDetail,
                                                     Date opTime) {
        // 订单操作有可能没有师傅：派单撤回/分单撤回后没有再次派单，直接操作了取消，这种情况保费由平台负责
        Integer orderWorkMasterId = orderWork.getMasterId();
        if (orderWorkMasterId == null || orderWorkMasterId.intValue() == 0 ) {
            return null;
        }
        if (Objects.equals(GlobalConsts.PLAT_MARK_YEYX, orderWork.getPlatWork())) {
            // 言而有信的订单，不购买保险
            return null;
        }

        InsOrderMasterSync insOrderMasterSync = new InsOrderMasterSync();
        // 同步信息
        insOrderMasterSync.setInsOrderId(dbInsOrder.getInsId());
        insOrderMasterSync.setOrderId(orderWork.getOrderId());
        insOrderMasterSync.setPlat(orderWork.getPlatWork());
        insOrderMasterSync.setInsStartTime(dbInsOrder.getCreateTime());
        insOrderMasterSync.setInsEndTime(opTime);
        insOrderMasterSync.setCityId(orderWork.getCityId());
        insOrderMasterSync.setCompanyId(orderWork.getCompanyId());
        insOrderMasterSync.setCompanyName(orderWork.getCompanyName());
        insOrderMasterSync.setManageCompanyId(orderWork.getManageCompanyId());
        insOrderMasterSync.setManageCompanyName(orderWork.getManageCompanyName());
        // 补充产品信息
        insOrderMasterSync.setServCategId(dbInsOrder.getServCategId());
        insOrderMasterSync.setCategOneId(dbInsOrder.getCategOneId());
        insOrderMasterSync.setCategId(dbInsOrder.getCategId());
        insOrderMasterSync.setProductId(dbInsOrder.getProductId());
        insOrderMasterSync.setCategTag(dbInsOrder.getCategTag());
        do {// 补充师傅信息
            // 主师傅不变
            if (Objects.equals(dbInsOrder.getMasterId(), orderWorkMasterId)) {
                insOrderMasterSync.setMasterId(dbInsOrder.getMasterId());
                insOrderMasterSync.setMasterName(dbInsOrder.getMasterName());
                insOrderMasterSync.setMasterMoblie(dbInsOrder.getMasterPhone());
                break;
            }
            // 到这里，说明主师傅换人了，需获取新的主师傅信息
            ForeignEngineerDetailInfoDRO mastMasterDRO = this._queryMasterInfo(orderWorkMasterId);
            if (mastMasterDRO != null) {
                insOrderMasterSync.setMasterId(mastMasterDRO.getEngineerId());
                insOrderMasterSync.setMasterName(mastMasterDRO.getRealName());
                insOrderMasterSync.setMasterMoblie(mastMasterDRO.getMobile());
                break;
            }
            // 进入这里，说明dubbo接口查师傅信息失败了
            // 1. 尝试从参保师傅数据中恢复师傅信息
            InsOrderMasterQuery insOrderMasterQuery = new InsOrderMasterQuery();
            insOrderMasterQuery.setInsId(dbInsOrder.getInsId());
            insOrderMasterQuery.setStatus(GlobalConsts.YES);
            List<InsOrderMaster> dbInsOrderMasters = insOrderBService.listInsOrderMasters(insOrderMasterQuery);
            if (dbInsOrderMasters != null && dbInsOrderMasters.size() > 0) {
                InsOrderMaster currentInsOrderMaster = null;
                for (InsOrderMaster item : dbInsOrderMasters) {
                    if (Objects.equals(item.getMasterId(), orderWorkMasterId)) {
                        currentInsOrderMaster = item;
                        break;
                    }
                }
                if (currentInsOrderMaster != null) {
                    insOrderMasterSync.setMasterId(orderWorkMasterId);
                    insOrderMasterSync.setMasterName(currentInsOrderMaster.getMasterName());
                    insOrderMasterSync.setMasterMoblie(currentInsOrderMaster.getMasterPhone());
                    break;
                }
            }
            // 2. 无法恢复数据，生成有问题数据，由人工去处理
            insOrderMasterSync.setMasterId(orderWorkMasterId);
            insOrderMasterSync.setMasterName("");
            insOrderMasterSync.setMasterMoblie("");
        } while (false);

        // 兼容未完成订单的老数据
        try {
            if (insOrderMasterSync.getCategTag() == null) {
                InsConsts.InsOrderLevel insOrderLevel = InsConsts.getInsOrderLevel(orderDetail.getServCategId(),
                        orderDetail.getCategOneId(), orderDetail.getCategId());
                insOrderMasterSync.setCategTag(insOrderLevel.getCategTag());

                insOrderMasterSync.setServCategId(orderDetail.getServCategId());
                insOrderMasterSync.setCategOneId(orderDetail.getCategOneId());
                insOrderMasterSync.setCategId(orderDetail.getCategId());
                insOrderMasterSync.setProductId(orderDetail.getProductId());

                insOrderMasterSync.setCompanyId(orderWork.getCompanyId());
                insOrderMasterSync.setCompanyName(orderWork.getCompanyName());
                insOrderMasterSync.setManageCompanyId(orderWork.getManageCompanyId());
                insOrderMasterSync.setManageCompanyName(orderWork.getManageCompanyName());
            }
        } catch (Exception e) {
            log.error(String.format("【%s】补全按单保险师傅同步数据失败: %s", LOG_HEAD, e.getMessage()), e);
        }

        return insOrderMasterSync;
    }

    /**
     * 构建师傅保险订单实例
     * @param orderWork
     * @param orderDetail
     * @param orderMaster
     * @return
     */
    private InsOrder _buildInsOrder(OrderWork orderWork, OrderDetail orderDetail, OrderMaster orderMaster) {
        InsOrder newInsOrder = BeanMapper.map(orderWork, InsOrder.class);
        // 地址信息
        newInsOrder.setUserAddress(String.format("%s%s%s",
                orderDetail.getCountyName(), orderDetail.getStreet(), orderDetail.getAddress()));
        newInsOrder.setNaturalCityName(orderDetail.getNaturalCityName());
        // 产品信息
        newInsOrder.setProductGroupId(orderDetail.getProductGroupId());
        newInsOrder.setProductGroupName(orderDetail.getProductGroupName());
        newInsOrder.setServCategId(orderDetail.getServCategId());
        newInsOrder.setCategOneId(orderDetail.getCategOneId());
        newInsOrder.setCategId(orderDetail.getCategId());
        newInsOrder.setProductId(orderWork.getShowProductId());
        {// 师傅信息
            ForeignEngineerDetailInfoDRO mastMasterDRO = _queryMasterInfo(orderMaster.getMasterId());
            if (mastMasterDRO == null) {
                mastMasterDRO = new ForeignEngineerDetailInfoDRO();
                mastMasterDRO.setEngineerId(orderMaster.getMasterId());
                mastMasterDRO.setRealName(orderMaster.getMasterName());
                mastMasterDRO.setIdcard("-");
                mastMasterDRO.setMobile(orderMaster.getMasterPhone());
            }
            newInsOrder.setMasterCardNo(mastMasterDRO.getIdcard());
            newInsOrder.setMasterId(mastMasterDRO.getEngineerId());
            newInsOrder.setMasterName(mastMasterDRO.getRealName());
            newInsOrder.setMasterPhone(mastMasterDRO.getMobile());
        }
        // 计价信息
        InsConsts.InsOrderLevel insOrderLevel = InsConsts.getInsOrderLevel(orderDetail.getServCategId(),
                orderDetail.getCategOneId(), orderDetail.getCategId());
        newInsOrder.setProductInfo(insOrderLevel.getCategName());
        newInsOrder.setCategTag(insOrderLevel.getCategTag());
        newInsOrder.setPriceLevel(insOrderLevel.getPriceLevel());

        return newInsOrder;
    }

    /**
     * 构建修改师傅保险订单实例
     * @param dbInsOrder
     * @param orderDetail
     * @return
     */
    private InsOrder _buildUpdateInsOrder(InsOrder dbInsOrder, OrderWork orderWork, OrderDetail orderDetail) {
        InsOrder updateInsOrder = new InsOrder();
        // 订单状态变更信息
        updateInsOrder.setInsId(dbInsOrder.getInsId());
        updateInsOrder.setPlatWork(orderWork.getPlatWork());
        updateInsOrder.setStatus(orderWork.getStatus());
        updateInsOrder.setResultStatus(orderWork.getResultStatus());
        // 地址 & 分公司信息
        updateInsOrder.setCityId(orderWork.getCityId());
        updateInsOrder.setCompanyId(orderWork.getCompanyId());
        updateInsOrder.setCompanyName(orderWork.getCompanyName());
        updateInsOrder.setManageCompanyId(orderWork.getManageCompanyId());
        updateInsOrder.setManageCompanyName(orderWork.getManageCompanyName());
        updateInsOrder.setNaturalCityName(orderDetail.getNaturalCityName());
        updateInsOrder.setUserAddress(String.format("%s%s%s",
                orderDetail.getCountyName(), orderDetail.getStreet(), orderDetail.getAddress()));
        do {// 师傅信息
            // 订单操作有可能没有师傅(为订单结束)：派单撤回/分单撤回后没有再次派单，直接操作了取消
            Integer orderWorkMasterId = orderWork.getMasterId();
            if (orderWorkMasterId == null || orderWorkMasterId.intValue() == 0) {
                updateInsOrder.setMasterId(0);
                updateInsOrder.setMasterName("");
                updateInsOrder.setMasterPhone("");
                updateInsOrder.setMasterCardNo("");
                break;
            }
            // 主师傅没变，无需更新
            if (Objects.equals(dbInsOrder.getMasterId(), orderWorkMasterId)) {
                break;
            }
            // 到这里，说明主师傅换人了，需更新主师傅信息
            ForeignEngineerDetailInfoDRO mastMasterDRO = this._queryMasterInfo(orderWorkMasterId);
            if (mastMasterDRO != null) {
                updateInsOrder.setMasterCardNo(mastMasterDRO.getIdcard());
                updateInsOrder.setMasterId(mastMasterDRO.getEngineerId());
                updateInsOrder.setMasterName(mastMasterDRO.getRealName());
                updateInsOrder.setMasterPhone(mastMasterDRO.getMobile());
                break;
            }
            // 进入这里，说明dubbo接口查师傅信息失败了
            // 1. 尝试从订单师傅数据中恢复师傅信息
            List<OrderMaster> dbOrderMasters = orderMasterService
                    .listMasterByWorkId(orderWork.getOrderId(), orderWork.getWorkId());
            if (dbOrderMasters != null && dbOrderMasters.size() > 0) {
                OrderMaster currentOrderMaster = null;
                for (OrderMaster item : dbOrderMasters) {
                    if (Objects.equals(item.getMasterId(), orderWorkMasterId)) {
                        currentOrderMaster = item;
                        break;
                    }
                }
                if (currentOrderMaster != null) {
                    updateInsOrder.setMasterId(currentOrderMaster.getMasterId());
                    updateInsOrder.setMasterName(currentOrderMaster.getMasterName());
                    updateInsOrder.setMasterPhone(currentOrderMaster.getMasterPhone());
                    updateInsOrder.setMasterCardNo("-");
                    break;
                }
            }
        } while (false);

        return updateInsOrder;
    }

    /**
     * 构建保险单师傅实例
     * @param insOrder
     * @param dbInsOrder
     * @param isMainMaster  是否为主师傅
     * @param inWarrity    是否在保
     * @return
     */
    private InsOrderMaster _buildInsOrderMaster(InsOrder insOrder,
                                                InsOrder dbInsOrder,
                                                boolean isMainMaster,
                                                boolean inWarrity,
                                                OrderMaster orderMaster) {
        InsOrderMaster insOrderMaster = new InsOrderMaster();
        insOrderMaster.setInsId(insOrder.getInsId());
        insOrderMaster.setPlatWork(insOrder.getPlatWork());
        insOrderMaster.setOrderId(insOrder.getOrderId());

        if (dbInsOrder != null) {
            insOrderMaster.setInsId(dbInsOrder.getInsId());
            insOrderMaster.setOrderId(dbInsOrder.getOrderId());
        }

        // 没有OrderMaster传入，代表新增insOrder，师傅信息使用insOrder中的信息
        if (orderMaster == null) {
            insOrderMaster.setMasterCardNo(insOrder.getMasterCardNo());
            insOrderMaster.setMasterId(insOrder.getMasterId());
            insOrderMaster.setMasterName(insOrder.getMasterName());
            insOrderMaster.setMasterPhone(insOrder.getMasterPhone());
        }
        // 传入了OrderMaster，代表修改insOrder，师傅信息使用OrderMaster对应的师傅信息
        else {
            ForeignEngineerDetailInfoDRO mastMasterDRO = _queryMasterInfo(orderMaster.getMasterId());
            if (mastMasterDRO == null) {
                mastMasterDRO = new ForeignEngineerDetailInfoDRO();
                mastMasterDRO.setEngineerId(orderMaster.getMasterId());
                mastMasterDRO.setRealName(orderMaster.getMasterName());
                mastMasterDRO.setIdcard("-");
                mastMasterDRO.setMobile(orderMaster.getMasterPhone());
            }

            insOrderMaster.setMasterCardNo(mastMasterDRO.getIdcard());
            insOrderMaster.setMasterId(mastMasterDRO.getEngineerId());
            insOrderMaster.setMasterName(mastMasterDRO.getRealName());
            insOrderMaster.setMasterPhone(mastMasterDRO.getMobile());
        }

        // 主工程师
        insOrderMaster.setType(isMainMaster ? OrderConsts.ORDER_MASTER_TYPE_MAIN : OrderConsts.ORDER_MASTER_TYPE_SLAVE);
        insOrderMaster.setStatus(inWarrity ? GlobalConsts.YES : GlobalConsts.NO);

        return insOrderMaster;
    }


    private ForeignEngineerDetailInfoDRO _queryMasterInfo(Integer masterId) {
        if (NumberUtil.isNullOrZero(masterId)) {
            return null;
        }
        try { // ResponseDTO<BaseEngineerDRO> responseDTO =
            log.debug("【{}】查询师傅信息-Request: masterId=[{}]", LOG_HEAD, masterId);
            // todo fubiao
            log.info("_queryMasterInfo#getEngineerDetailById 入参 [{}]",masterId);
            ResponseDTO<ForeignEngineerDetailInfoDRO> responseDTO = engineerListRemoteService.getEngineerDetailById(masterId);
            log.info("_queryMasterInfo#getEngineerDetailById 出参 [{}]",JSON.toJSONString(responseDTO));
            log.debug("【{}】查询师傅信息-Response: responseDTO=[{}]", LOG_HEAD, JSON.toJSONString(responseDTO));
            return responseDTO.getData();
        } catch (Exception e) {
            log.error(String.format("【%s】查询师傅信息失败: %s", LOG_HEAD, e.getMessage()), e);
        }
        return null;
    }

}
